import { RouteRecordRaw } from "vue-router";
import Index from "@/views/layout/index.vue";
import { markRaw, shallowRef } from "vue";
import { getToken } from "@/library/utils";
import { OperatorApi } from "@/api/operator";
import router from "./index";

// 静态路由
import { permessionRouter } from "./staticRouter"

// 需要排除的菜单
const REMOVE_MENU_LIST = ["rbac_manager"]

/**
 * @description 动态生成路由配置
 * @param routes 总路由数据
 * @param isFirst 是否一级路由
 * @param parentPath 父级路由
 * @returns 路由应用 路由列表 routes
 */
export const InitRouter = (routes: any[], isFirst = true, parentPath?: string) => {
    // 路由集合
    let newRoutesObj: any[] = []

    routes.map((item) => {
        if (!REMOVE_MENU_LIST.includes(item.ClassName)) {
            // 路由
            let newRoute: any = {
                path: ("/" + item.Url),
                name: item.ClassName,
                meta: {
                    icon: item.Icon,
                    title: item.Name,
                    auth: false
                },
                component: useComponent(item.Url, isFirst, parentPath),
            }

            if (item.Children.length) {
                newRoute.children = InitRouter(item.Children, false, item.Url)
            }

            newRoutesObj.push(newRoute)
        }
    })

    return newRoutesObj
}

/**
 * @description 返回当前路由应用组件
 * @param path 路由路径
 * @param isFirst 是否一级路由
 * @returns 应用组件
 */
const useComponent = (path: string, isFirst = true, parentPath?: string) => {
    // 一级路由
    if (isFirst) { return markRaw(Index) }

    // 二级路由
    try {
        // 以下引入路径不存在(未创建组件)执行 catch
        require(`@/views/${parentPath}/${path}/Index.vue`)
        return () => import(`@/views/${parentPath}/${path}/Index.vue`)
    } catch (error) {
        // 当前未创建组件
        return () => import("@/views/errors/404.vue")
    }
}

/** 菜单数据 */
const menuTree = shallowRef<any[]>([])

/** 路由集合 */
const routesList = shallowRef<RouteRecordRaw[]>([]);

/** 上次使用的 token */
let LastUsedToken = ""

/** 需要重置路由 */
let routeArr: string[] = []

/**
 * @description 判断当前登录状态
 * @param token 登录令牌
 * @returns boolean
 */
const tokenIsEqual = (token: string) => {
    if (token !== LastUsedToken) {
        LastUsedToken = token
        return true
    }

    return false
}

/**
 * @description 重置路由
 * @param Router 路由
 */
const resetRouter = (Router = router) => {
    if (!routeArr.length) { return }

    routeArr.forEach(route => {
        Router.removeRoute(route)
    })

    routeArr = []
}

/**
 * @description 初始化动态路由
 * @param Router 路由
 * @returns routes 路由数据 和 菜单数据
 * @returns returns.routes 路由数据
 * @returns returns.menuTree 菜单数据
 */
export const initDynamicRouter = async (Router = router) => {
    // 当前登录 token
    let token = getToken().token

    if (token && tokenIsEqual(token)) {

        resetRouter(Router)

        // 获取 menu 路由数据
        const res = await OperatorApi.GetMenuTree()
        menuTree.value = res.Data

        // 生成的路由
        let Routes = InitRouter(res.Data)

        let menuLists = res.Data?.map((v: any) => v.ClassName) || []
        if (menuLists.includes("rbac_manager")) {
            Routes.push(...permessionRouter)
        }

        routesList.value = [...permessionRouter, ...Routes]

        // 应用对应路由
        for (const route of Routes) {
            Router.addRoute(route)
            routeArr.push(route.name)
        }
    }

    return {
        routes: routesList.value,
        menuTree: menuTree.value
    }
}